<?php

/*
 * This file is part of PHP CS Fixer.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *     Dariusz Rumiński <dariusz.ruminski@gmail.com>
 *
 * This source file is subject to the MIT license that is bundled
 * with this source code in the file LICENSE.
 */

namespace app\http\middleware;

use app\api\lib\Token;
use app\common\job\Log;
use app\http\exception\ApiException;
use lib\MyRedis;

use think\Queue;
use think\queue\Job;
use think\Request;
use think\Response;

class ApiAuth {
    /**
     *
     * @param Request  $request
     * @param \Closure $next
     *
     * @return mixed
     * @throws ApiException
     * @author : Randy_chen
     * @Date   : 2020/4/24
     * @Time   : 9:20
     */
    public function handle(Request $request, \Closure $next) {
        //获取请求头
        $this->check(\request()->header(), $request);
        $this->checkJwt(\request()->header(), $request);
        $this->currentLimit($request);
        $response = $next($request);
        $this->log($request, $response);
        return $response;
    }

    /**
     * JWT检测
     *
     * @param         $header
     * @param Request $request
     *
     * @return bool
     * @throws ApiException
     * @author : Randy_chen
     * @Date   : 2020/4/23
     * @Time   : 17:09
     */
    public function checkJwt($header, Request $request) {
        $authorization = ltrim($header['authorization'], 'Basic ');
        $data = Token::check($authorization);
        $request->uid = $data['uid'];
        $request->app_type = $data['app_type'];
        $data = array_merge(input(), $data);
        $request->body = $data;
        return true;
    }


    /**
     * 签名检测
     *
     * @param         $header
     *
     * @param Request $request
     *
     * @throws ApiException
     * @author : Randy_chen
     * @Date   : 2019/8/19
     * @Time   : 15:29
     */
    public function check($header, Request $request) {
        return true;
        $str = '';
        if ($header['openid'] && $header['source'] && $header['timestamp'] && $header['authorization']) {
            if ($header['openid']) {
                $str .= 'openid';
                $str .= $header['openid'];
            }
            if ($header['source']) {
                $str .= 'source';
                $str .= $header['source'];
            }
            if ($header['timestamp']) {
                $str .= 'timestamp';
                $str .= $header['timestamp'];
            }
            if ($header['authorization']) {
                $str .= 'authorization';
                $str .= $header['authorization'];
            }
            $sign = md5(md5($str) . 'zb_wei');
            if ($sign !== $header['sign']) {
                throw new ApiException(10001);
            }
        } else {
            throw new ApiException(10100);
        }

    }

    /**
     * 接口访问限流
     *
     * @param Request $request
     *
     * @throws ApiException
     * @author : Randy_chen
     * @Date   : 2020/4/24
     * @Time   : 9:16
     */
    public function currentLimit(Request $request) {
        $ip = $request->ip(1);
        $key = 'currentLimit:ip:' . $ip;
        $redis = MyRedis::getInstance();
        if ($request->uid) {
            $userKey = 'currentLimit:user:' . $request->uid;
            if ($redis->lLen($userKey) > config('api.user_limit')) {
                throw new ApiException(11007);
            }
            $redis->lPush($userKey, 1);
            $redis->expire($userKey, 10);
        }
        //判断请求数
        if ($redis->lLen($key) > config('api.ip_limit')) {
            throw new ApiException(11006);
        }
        $redis->lPush($key, 1);
        $redis->expire($key, 10);
    }

    //记录接口访问日志
    public function log(Request $request, Response $response) {
        $responseData = $response->getData();
        $data['uid'] = $request->uid;
        $data['app_type'] = $request->app_type;
        $data['header'] = json_encode($request->header(),JSON_UNESCAPED_UNICODE);
        $data['query'] = json_encode($request->query(),JSON_UNESCAPED_UNICODE);
        $data['url'] = $request->url();
        $data['ip'] = $request->ip();
        $data['method'] = $request->method();
        $data['create_time'] = date('Y-m-d H:i:s');
        $data['version'] = $request->param('version');
        $data['action'] = $request->param('function') ? : $request->action();
        $data['controller'] = $request->param('controller') ? : $request->controller();
        $data['request'] = json_encode($request->param(), JSON_UNESCAPED_UNICODE);
        $data['response'] = json_encode($response->getData(), JSON_UNESCAPED_UNICODE);
        $data['request_time'] = get_microtime_format($request->time(true));
        $data['response_time'] = get_microtime_format(microtime(true));
        $data['duration_time'] = intval((microtime(true) - $request->time(true)) * 1000);
        $data['code'] = $responseData['code'];
        $data['msg'] = $responseData['msg'];
        $data['trans_id'] = $request->param('transID', '');
        Db::name('api_log')->strict(false)->insert($data);
        //添加至消息队列处理.
//        Queue::push(Log::URL, $data);
    }
}
